﻿using LiveChartsCore;
using LiveChartsCore.SkiaSharpView;
using LiveChartsCore.SkiaSharpView.Painting;
using LiveChartsCore.SkiaSharpView.WPF;
using Microsoft.Win32;
using PLC.Interface.ActualDatas;
using PLC.Interface.Stations;
using PLCWpfTest.Common;
using PLCWpfTest.Common.Extensions;
using PLCWpfTest.Models;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using YWM.DoubleCommom;

namespace PLCWpfTest.ViewModels
{
    public class HistoricalTrendViewModel : BaseViewModel
    {
        private readonly IActualDataAppService _actualDataAppService;

        public RelayCommand OkCommand { get; set; }

        private IReadOnlyList<ActualDataResultDto> _actualDatas = new List<ActualDataResultDto>();

        public ActualDataResultRequestDto Query { get; set; }

        /// <summary>
        /// 温湿度模型集合
        /// </summary>
        public ObservableCollection<NameValueSelectedModel<long>> THCollection { get; set; } = new ObservableCollection<NameValueSelectedModel<long>>();

        /// <summary>
        /// 趋势图数据集合
        /// </summary>
        public ObservableCollection<ISeries> Series { get; set; } = new ObservableCollection<ISeries>();

        /// <summary>
        /// 趋势图X轴集合
        /// </summary>
        public Axis[] XAxes { get; set; } = {
            new Axis
            {
                Labeler = value => value < 0 ? string.Empty : new DateTime((long)value).ToString("HH:mm:ss"),
                LabelsPaint = new SolidColorPaint(SKColors.White),
                UnitWidth = TimeSpan.FromHours(1).Ticks,
                MinStep = TimeSpan.FromHours(1).Ticks
            }
        };

        /// <summary>
        /// 趋势图Y轴集合
        /// </summary>
        public Axis[] YAxes { get; set; } = {
            new Axis
            {
                MinLimit = 0,
                MaxLimit = 100,
                LabelsPaint = new SolidColorPaint(SKColors.White)
            }
        };

        /// <summary>
        /// 提示文本对象
        /// </summary>
        public SolidColorPaint TooltipTextPaint { get; set; } = new SolidColorPaint
        {
            Color = SKColors.Black,
            SKTypeface = SKTypeface.FromFamilyName(FONT_FAMILY_NAME_MICROSOFT_YAHEI)
        };

        /// <summary>
        /// 铭文文本对象
        /// </summary>
        public SolidColorPaint LegendTextPaint { get; set; } = new SolidColorPaint
        {
            Color = SKColors.White,
            SKTypeface = SKTypeface.FromFamilyName(FONT_FAMILY_NAME_MICROSOFT_YAHEI)
        };

        public HistoricalTrendViewModel(IActualDataAppService actualDataAppService, RelayCommand okCommand, RelayCommand selectCommand)
        {
            _actualDataAppService = actualDataAppService;
            OkCommand = okCommand;
            OkCommand.BeforeCanExecute += OkCommand_BeforeCanExecute;
            OkCommand.Executing += OkCommand_Executing;
            selectCommand.Executing += SelectCommand_Executing;
            DateTime now = DateTime.Now;
            Query = new ActualDataResultRequestDto { MaxResultCount = int.MaxValue, StartTime = DateTime.Today.AddHours(now.Hour), EndTime = DateTime.Today.AddHours(now.Hour + 1).AddSeconds(-1) };
            string format = Lang["站点"], tempName = Lang["温度"], humidtyName = Lang["湿度"];
            foreach (StationResultDto station in DataCache.Stations)
            {
                string title = string.Format(format, station.Identifier);
                NameValueSelectedModel<long> tempModel = new NameValueSelectedModel<long>($"{title}{tempName}", station.StationVariable.TempId, station.Identifier == 1) { SelectCommand = selectCommand };
                NameValueSelectedModel<long> humidityModel = new NameValueSelectedModel<long>($"{title}{humidtyName}", station.StationVariable.HumidityId, station.Identifier == 1) { SelectCommand = selectCommand };
                THCollection.Add(tempModel);
                THCollection.Add(humidityModel);
                if (station.Identifier == 1)
                {
                    AddSerie(tempModel);
                    AddSerie(humidityModel);
                }
            }
        }

        protected override bool LoadCommand_BeforeCanExecute(object parameter)
        {
            return Query.StartTime != null && Query.EndTime != null;
        }

        protected override bool LoadCommand_BeforeExecute(object parameter)
        {
            if (DateTime.Compare(Query.StartTime.Value, Query.EndTime.Value) >= 0)
            {
                this.ShowWarning("结束时间不能小于开始时间");
                return false;
            }
            return true;
        }

        protected override async Task LoadCommand_Executing(object parameter)
        {
            _actualDatas = await _actualDataAppService.GetList(Query);
            XAxes[0].MinLimit = Query.StartTime.Value.Ticks;
            XAxes[0].MaxLimit = Query.EndTime.Value.Ticks;
            foreach (LineSeries<ActualDataResultDto> item in Series)
            {
                item.Values = new ObservableCollection<ActualDataResultDto>(_actualDatas.Where(ad => ad.VariableId == (long)item.Tag));
            }
        }

        private void SelectCommand_Executing(object parameter)
        {
            long id = (long)parameter;
            NameValueSelectedModel<long> thModel = THCollection.FirstOrDefault(th => th.Value == id);
            if (thModel == null)
            {
                return;
            }
            ISeries sv = Series.FirstOrDefault(s => id == (long)((LineSeries<ActualDataResultDto>)s).Tag);
            if (sv == null && thModel.IsSelected)
            {
                AddSerie(thModel);
            }
            else if (sv != null && !thModel.IsSelected)
            {
                Series.Remove(sv);
            }
        }

        private void AddSerie(NameValueSelectedModel<long> thModel)
        {
            Series.Add(new LineSeries<ActualDataResultDto>
            {
                Tag = thModel.Value,
                Name = thModel.Name,
                Fill = null,
                GeometryFill = null,
                GeometryStroke = null,
                Values = new ObservableCollection<ActualDataResultDto>(_actualDatas.Where(ad => ad.VariableId == thModel.Value)),
                Mapping = (actualData, point) =>
                {
                    point.SecondaryValue = actualData.CreationTime.Ticks;
                    point.PrimaryValue = actualData.Value;
                }
            });
        }

        private bool OkCommand_BeforeCanExecute(object parameter)
        {
            if (parameter is CartesianChart)
            {
                return Series.Count > 0 && ((ObservableCollection<ActualDataResultDto>)Series[0].Values).Count > 0;
            }
            return _actualDatas.Count > 0;
        }

        private void OkCommand_Executing(object parameter)
        {
            SaveFileDialog saveFileDialog;
            if (parameter is CartesianChart)
            {
                CartesianChart chart = (CartesianChart)parameter;
                saveFileDialog = GetSaveFileDialog(Lang["保存Img"], "jpeg (*.jpeg)|*.jpeg|png (*.png)|*.png");
                if (saveFileDialog.ShowDialog() == true)
                {
                    //找到lvc的父控件
                    Border border = (Border)chart.Parent;
                    using (FileStream fs = new FileStream($"{saveFileDialog.FileName}", FileMode.Create))
                    {
                        //改变背景色
                        border.Background = new ImageBrush(new BitmapImage(new Uri(Application.Current.FindResource("BackGroundPath").ToString())));
                        //获取控件大小
                        border.Measure(chart.RenderSize);
                        //更新布局
                        border.UpdateLayout();
                        int width = (int)border.ActualWidth + 10;
                        int height = (int)border.ActualHeight + 100;
                        int dpiX = (int)typeof(SystemParameters).GetProperty("DpiX", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
                        int dpiY = (int)typeof(SystemParameters).GetProperty("Dpi", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null, null);
                        //对象转换成位图
                        RenderTargetBitmap bmp = new RenderTargetBitmap(width, height, dpiX, dpiY, PixelFormats.Pbgra32);
                        DrawingVisual dv = new DrawingVisual();
                        using (DrawingContext dc = dv.RenderOpen())
                        {
                            dc.DrawRectangle(new VisualBrush(border), null, new Rect(0, 0, width, height));
                        }
                        bmp.Render(dv);
                        //对象的集合编码转成图像流
                        BitmapEncoder encoder = new PngBitmapEncoder();
                        encoder.Frames.Add(BitmapFrame.Create(bmp));
                        //保存到路径中
                        encoder.Save(fs);
                    }
                    //恢复原来背景色
                    border.Background = Brushes.Transparent;
                }
            }
            else
            {
                saveFileDialog = GetSaveFileDialog(Lang["导出Excel"], "Excel files (*.xlsx)|*.xlsx");
                if (saveFileDialog.ShowDialog() == true)
                {
                    Task.Factory.StartNew(state =>
                    {
                        ExcelUtil.Export((System.Collections.ICollection)_actualDatas, state.ToString(), new Dictionary<string, string>
                        {
                            {"DisplayName",Lang["传感器名"]},
                            {"Value",Lang["传感器值"]},
                            {"CreationTime",Lang["创建时间"]}
                        });
                    }, saveFileDialog.FileName);
                    this.ShowInfo("正在导出Excel,请稍后查看文件");
                }
            }
        }

        private SaveFileDialog GetSaveFileDialog(string title, string filter)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.RestoreDirectory = true;
            saveFileDialog.Title = title;
            saveFileDialog.FileName = $"{Lang["历史趋势"]}{DateTime.Now.ToString("yyyyMMddHHmmss")}";
            saveFileDialog.Filter = filter;
            return saveFileDialog;
        }
    }
}
